

package com.maoshi.shop.service.impl;

import cn.hutool.core.collection.CollUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.maoshi.shop.bean.model.Category;
import com.maoshi.shop.bean.param.CategoryScoreConfigParam;
import com.maoshi.shop.bean.param.ScoreConfigParam;
import com.maoshi.shop.common.config.Constant;
import com.maoshi.shop.common.exception.MaoshiShopBindException;
import com.maoshi.shop.dao.CategoryBrandMapper;
import com.maoshi.shop.dao.CategoryMapper;
import com.maoshi.shop.dao.CategoryPropMapper;
import com.maoshi.shop.service.CategoryService;
import com.maoshi.shop.service.SysConfigService;
import lombok.AllArgsConstructor;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.cache.annotation.Caching;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.Objects;

/**
 * @author LGH
 */
@Service
@AllArgsConstructor
public class CategoryServiceImpl extends ServiceImpl<CategoryMapper, Category> implements CategoryService{

	private final CategoryMapper categoryMapper;

	private final CategoryBrandMapper categoryBrandMapper;

	private final CategoryPropMapper categoryPropMapper;

	private SysConfigService sysConfigService;

	@Override
	@Transactional(rollbackFor = Exception.class)
//	@CacheEvict(cacheNames = "CategoryListByParentIdAndShopId", key = "#category.parentId + ':' + #category.shopId")
	@Caching(evict = {
			@CacheEvict(cacheNames = "CategoryListByParentIdAndShopId", key = "#category.parentId + ':' + #category.shopId"),
			@CacheEvict(cacheNames = "CategoryListByShopId", key = "#category.shopId + ':category'")
	})
	public void saveCategroy(Category category) {
		category.setRecTime(new Date());
		// 保存分类信息
		categoryMapper.insert(category);

		insertBrandsAndAttributes(category);

		if (Objects.equals(category.getParentId(),Constant.CATEGORY_ID)){
			this.addScoreConfig(category);
		}
	}

	@Override
	@Transactional(rollbackFor = Exception.class)
//	@CacheEvict(cacheNames = "CategoryListByParentIdAndShopId", key = "#category.parentId + ':' + #category.shopId")
	@Caching(evict = {
			@CacheEvict(cacheNames = "CategoryListByParentIdAndShopId", key = "#category.parentId + ':' + #category.shopId"),
			@CacheEvict(cacheNames = "CategoryListByShopId", key = "#category.shopId + ':category'")
	})
	public void updateCategroy(Category category) {
		category.setUpdateTime(new Date());
		// 保存分类信息
		categoryMapper.updateById(category);

		//修改积分配置中的分类数据
		if (!Objects.equals(category.getCategoryName(),category.getOldCategoryName())){
			this.updateScoreConfig(category);
		}
		// 先删除后增加
		deleteBrandsAndAttributes(category.getCategoryId());
		insertBrandsAndAttributes(category);
	}

	@Override
	@Transactional(rollbackFor = Exception.class)
//	@CacheEvict(cacheNames = "CategoryListByParentIdAndShopId", key = "#category.parentId + ':' + #category.shopId")
	@Caching(evict = {
			@CacheEvict(cacheNames = "CategoryListByParentIdAndShopId", key = "#category.parentId + ':' + #category.shopId"),
			@CacheEvict(cacheNames = "CategoryListByShopId", key = "#category.shopId + ':category'")
	})
	public void deleteCategroy(Category category) {
		//修改积分配置中的分类数据
		if (Objects.equals(category.getParentId(),Constant.CATEGORY_ID)){
			this.deleteScoreConfig(category);
		}
		categoryMapper.deleteById(category.getCategoryId());
		deleteBrandsAndAttributes(category.getCategoryId());
	}

	@Override
	public Category getCategoryByCategoryIdAndShopId(Long categoryId, Long shopId) {
		Category category = categoryMapper.selectOne(new LambdaQueryWrapper<Category>().eq(Category::getCategoryId, categoryId).eq(Category::getShopId, shopId));
		if (category == null) {
			throw new MaoshiShopBindException("无法获取分类信息");
		}
		return category;
	}

    @Override
    @Cacheable(cacheNames = "CategoryListByParentIdAndShopId", key = "#parentId + ':' + #shopId")
    public List<Category> listByParentIdAndShopId(Long parentId, Long shopId) {
        return categoryMapper.selectList(new LambdaQueryWrapper<Category>().eq(Category::getShopId,shopId).eq(Category::getParentId,parentId).eq(Category::getStatus, 1).orderByAsc(Category::getSeq));
    }

	@Override
	@Cacheable(cacheNames = "CategoryListByShopId", key = "#shopId + ':category'")
	public List<Category> listByShopId(Long shopId) {
		return categoryMapper.selectList(new LambdaQueryWrapper<Category>().eq(Category::getShopId,shopId));
	}


	private void deleteBrandsAndAttributes(Long categoryId) {
		// 删除所有分类所关联的品牌
		categoryBrandMapper.deleteByCategoryId(categoryId);
		// 删除所有分类所关联的参数
		categoryPropMapper.deleteByCategoryId(categoryId);
	}

	private void insertBrandsAndAttributes(Category category) {
		//保存分类与品牌信息
		if(CollUtil.isNotEmpty(category.getBrandIds())){
			categoryBrandMapper.insertCategoryBrand(category.getCategoryId(), category.getBrandIds());
		}

		//保存分类与参数信息
		if(CollUtil.isNotEmpty(category.getAttributeIds())){
			categoryPropMapper.insertCategoryProp(category.getCategoryId(), category.getAttributeIds());
		}
	}
	private void addScoreConfig(Category category) {
		//新增积分配置中的分类数据
		ScoreConfigParam scoreParamDb = sysConfigService.getSysConfigObject(Constant.SCORE_CONFIG,ScoreConfigParam.class);
		CategoryScoreConfigParam categoryScoreConfigParam = new CategoryScoreConfigParam();
		categoryScoreConfigParam.setCategoryId(category.getCategoryId());
		categoryScoreConfigParam.setCategoryName(category.getCategoryName());
		categoryScoreConfigParam.setGetScoreLimit(0.00);
		categoryScoreConfigParam.setUseScoreLimit(0.00);
		scoreParamDb.getCategoryConfigs().add(categoryScoreConfigParam);
		sysConfigService.saveOrUpdateSysConfigService(scoreParamDb,Constant.SCORE_CONFIG);
	}

	private void updateScoreConfig(Category category) {
		//更新积分配置中的分类数据
		ScoreConfigParam scoreParamDb = sysConfigService.getSysConfigObject(Constant.SCORE_CONFIG,ScoreConfigParam.class);
		List<CategoryScoreConfigParam> categoryConfigs = scoreParamDb.getCategoryConfigs();
		for (CategoryScoreConfigParam categoryScoreConfigParam :categoryConfigs){
			if (Objects.equals(categoryScoreConfigParam.getCategoryId(),category.getCategoryId())){
				categoryScoreConfigParam.setCategoryName(category.getCategoryName());
			}
		}
		sysConfigService.saveOrUpdateSysConfigService(scoreParamDb,Constant.SCORE_CONFIG);
	}

	private void deleteScoreConfig(Category category) {
		//删除积分配置中的分类数据
		ScoreConfigParam scoreParamDb = sysConfigService.getSysConfigObject(Constant.SCORE_CONFIG,ScoreConfigParam.class);
		Iterator<CategoryScoreConfigParam> iterator = scoreParamDb.getCategoryConfigs().iterator();
		while (iterator.hasNext()){
			CategoryScoreConfigParam next = iterator.next();
			if (Objects.equals(next.getCategoryId(),category.getCategoryId())){
				iterator.remove();
			}
		}
		sysConfigService.saveOrUpdateSysConfigService(scoreParamDb,Constant.SCORE_CONFIG);
	}
}
